home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsrmt / fsrmtDevice.c < prev    next >
C/C++ Source or Header  |  1990-12-07  |  24KB  |  726 lines

  1. /* 
  2.  * fsRmtDevice.c --
  3.  *
  4.  *    Routines to manage Remote device.
  5.  *
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /sprite/src/kernel/fsrmt/RCS/fsrmtDevice.c,v 9.8 90/12/06 21:56:08 jhh Exp $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include <sprite.h>
  24.  
  25. #include <fs.h>
  26. #include <fsconsist.h>
  27. #include <fsio.h>
  28. #include <fsutil.h>
  29. #include <fsNameOps.h>
  30. #include <fsrmtNameOpsInt.h>
  31. #include <fsdm.h>
  32. #include <fsioLock.h>
  33. #include <fsprefix.h>
  34. #include <fsrmt.h>
  35. #include <dev.h>
  36. #include <rpc.h>
  37. #include <recov.h>
  38. #include <fsStat.h>
  39. #include <fsioDevice.h>
  40. #include <devFsOpTable.h>
  41.  
  42. #include <stdio.h>
  43.  
  44. /*
  45.  * Parameters for RPC_FS_DEV_OPEN remote procedure call.
  46.  * The return value from this call is a new I/O fileID.
  47.  */
  48. typedef struct FsDeviceRemoteOpenParam {
  49.     Fs_FileID    fileID;        /* I/O fileID from name server. */
  50.     int        useFlags;    /* FS_READ | FS_WRITE ... */
  51.     int        dataSize;    /* size of openData */
  52.     FsrmtUnionData    openData;    /* Fsio_DeviceState or Fspdev_State.
  53.                  * NOTE. be careful when assigning this.
  54.                  * bcopy() of the whole union can cause
  55.                  * bus errors if really only a small object
  56.                  * exists and it's at the end of a page. */
  57. } FsDeviceRemoteOpenParam;
  58.  
  59.  
  60.  
  61.  
  62. /*
  63.  *----------------------------------------------------------------------
  64.  *
  65.  * FsrmtDeviceIoOpen --
  66.  *
  67.  *      Set up the stream IO handle for a remote device.  This makes
  68.  *    an RPC to the I/O server, which will invoke Fsio_DeviceIoOpen there,
  69.  *    and then sets up the remote device handle.
  70.  *
  71.  * Results:
  72.  *    SUCCESS or a device dependent open error code.
  73.  *
  74.  * Side effects:
  75.  *    Sets up and installs the remote device's ioHandle.
  76.  *    The use counts on the handle are updated.
  77.  *    The handle is returned unlocked, but with a new
  78.  *    reference than gets released when the device is closed.
  79.  *
  80.  *----------------------------------------------------------------------
  81.  */
  82. /*ARGSUSED*/
  83. ReturnStatus
  84. FsrmtDeviceIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name, ioHandlePtrPtr)
  85.     Fs_FileID        *ioFileIDPtr;    /* I/O fileID */
  86.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  87.     int            clientID;    /* Host doing the open */
  88.     ClientData        streamData;    /* Fsio_DeviceState */
  89.     char        *name;        /* Device file name */
  90.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a handle set up for
  91.                      * I/O to a device, NIL if failure. */
  92. {
  93.     register ReturnStatus     status;
  94.  
  95.     /*
  96.      * Do a device open at the I/O server.  We set the ioFileID type so
  97.      * that the local device client open procedure gets called at the I/O
  98.      * server, as opposed to the local pipe (or whatever) open routine.
  99.      * NAME note: are not passing the file name to the I/O server.
  100.      */
  101.     ioFileIDPtr->type = FSIO_LCL_DEVICE_STREAM;
  102.     status = Fsrmt_DeviceOpen(ioFileIDPtr, *flagsPtr,    sizeof(Fsio_DeviceState),
  103.                 streamData);
  104.     if (status == SUCCESS) {
  105.     ioFileIDPtr->type = FSIO_RMT_DEVICE_STREAM;
  106.     Fsrmt_IOHandleInit(ioFileIDPtr, *flagsPtr, name, ioHandlePtrPtr);
  107.     } else {
  108.     *ioHandlePtrPtr = (Fs_HandleHeader *)NIL;
  109.     }
  110.     free((Address)streamData);
  111.     return(status);
  112. }
  113.  
  114. /*
  115.  *----------------------------------------------------------------------
  116.  *
  117.  * Fsrmt_IOHandleInit --
  118.  *
  119.  *    Initialize a handle for a remote device/pseudo-device/whatever.
  120.  *
  121.  * Results:
  122.  *    Sets its *ioHandlePtrPtr to reference the installed handle.
  123.  *
  124.  * Side effects:
  125.  *    Create and install a handle for remote thing.  The handle is
  126.  *    returned unlocked.  The recovery use counts are incremented
  127.  *    to reflect the use of the handle.
  128.  *
  129.  *----------------------------------------------------------------------
  130.  */
  131. void
  132. Fsrmt_IOHandleInit(ioFileIDPtr, useFlags, name, newHandlePtrPtr)
  133.     Fs_FileID        *ioFileIDPtr;        /* Remote IO File ID */
  134.     int            useFlags;        /* Stream usage flags */
  135.     char        *name;            /* File name */
  136.     Fs_HandleHeader    **newHandlePtrPtr;    /* Return - installed handle */
  137. {
  138.     register Boolean found;
  139.     register Fsutil_RecoveryInfo *recovPtr;
  140.  
  141.     found = Fsutil_HandleInstall(ioFileIDPtr, sizeof(Fsrmt_IOHandle), name,
  142.             FALSE, newHandlePtrPtr);
  143.     recovPtr = &((Fsrmt_IOHandle *)*newHandlePtrPtr)->recovery;
  144.     if (!found) {
  145.     Fsutil_RecoveryInit(recovPtr);
  146.     fs_Stats.object.remote++;
  147.     /*
  148.      * Register a callback with the recovery module.  This ensures that
  149.      * someone is paying attention to the I/O server and the filesystem
  150.      * will get called back when the I/O server reboots.
  151.      */
  152.     Recov_RebootRegister(ioFileIDPtr->serverID, Fsutil_Reopen,
  153.                 (ClientData)NIL);
  154.     }
  155.     recovPtr->use.ref++;
  156.     if (useFlags & FS_WRITE) {
  157.     recovPtr->use.write++;
  158.     }
  159.     Fsutil_HandleUnlock(*newHandlePtrPtr);
  160. }
  161.  
  162. /*----------------------------------------------------------------------
  163.  *
  164.  * Fsrmt_DeviceOpen --
  165.  *
  166.  *    Client side stub to open a remote device, remote named pipe,
  167.  *    or remote pseudo stream.  Uses the RPC_FS_DEV_OPEN remote
  168.  *    procedure call to invoke the pipe, device, or pseudo device
  169.  *    open routine on the I/O server.  We are given an ioFileID from
  170.  *    the name server, although we just use the serverID part here.
  171.  *    The I/O server returns a new fileID that connects to the device.
  172.  *
  173.  * Results:
  174.  *    (May) modify *ioFileIDPtr.  Returns a status from the RPC or the
  175.  *    I/O device driver.
  176.  *
  177.  * Side effects:
  178.  *    Sets up a recovery reboot call-back for the I/O server if the remote
  179.  *    device open succeeds.
  180.  *
  181.  *----------------------------------------------------------------------
  182.  */
  183. ReturnStatus
  184. Fsrmt_DeviceOpen(ioFileIDPtr, useFlags, inSize, inBuffer)
  185.     Fs_FileID    *ioFileIDPtr;    /* Indicates I/O server.  This is modified
  186.                  * by the I/O server and returned to our
  187.                  * caller for use in the dev/pipe/etc handle */
  188.     int        useFlags;    /* FS_READ | FS_WRITE ... */
  189.     int        inSize;        /* Size of input parameters */
  190.     ClientData    inBuffer;    /* Input data for remote server */
  191. {
  192.     ReturnStatus    status;        /* Return code from RPC */
  193.     Rpc_Storage        storage;    /* Specifies inputs/outputs to RPC */
  194.     FsDeviceRemoteOpenParam param;
  195.  
  196.     param.fileID = *ioFileIDPtr;
  197.     param.useFlags = useFlags;
  198.     param.dataSize = inSize;
  199.     if (inSize > 0) {
  200.     bcopy((Address)inBuffer, (Address)¶m.openData, inSize);
  201.     }
  202.     storage.requestParamPtr = (Address) ¶m;
  203.     storage.requestParamSize = sizeof(FsDeviceRemoteOpenParam);
  204.     storage.requestDataPtr = (Address) NIL;
  205.     storage.requestDataSize = 0;
  206.     storage.replyParamPtr = (Address) ioFileIDPtr;
  207.     storage.replyParamSize = sizeof(Fs_FileID);
  208.     storage.replyDataPtr = (Address) NIL;
  209.     storage.replyDataSize = 0;
  210.  
  211.     status = Rpc_Call(ioFileIDPtr->serverID, RPC_FS_DEV_OPEN, &storage);
  212.  
  213.     return(status);
  214. }
  215.  
  216. /*
  217.  *----------------------------------------------------------------------
  218.  *
  219.  * Fsrmt_RpcDevOpen --
  220.  *
  221.  *    Server stub for the RPC_FS_DEV_OPEN call.
  222.  *    This host is the IO server for a handle.  This message from the
  223.  *    remote host indicates that a client process there will be
  224.  *    using us as the IO server.  This adds that client to the handle's
  225.  *    client list for recovery and consistency checks.  This then branches
  226.  *    to the file type client-open procedure to set up an I/O
  227.  *    handle for the (device, pipe, pseudo-device).
  228.  *
  229.  * Results:
  230.  *    If this procedure returns SUCCESS then a reply has been sent to
  231.  *    the client.  If the arguments are bad then an error is 
  232.  *    returned and the main RPC server level sends back an error reply.
  233.  *
  234.  * Side effects:
  235.  *
  236.  *----------------------------------------------------------------------
  237.  */
  238. /*ARGSUSED*/
  239. ReturnStatus
  240. Fsrmt_RpcDevOpen(srvToken, clientID, command, storagePtr)
  241.     ClientData          srvToken;    /* Handle on server process passed to
  242.                      * Rpc_Reply */
  243.     int          clientID;    /* Sprite ID of client host */
  244.     int          command;    /* Command identifier */
  245.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  246.                      * request buffers and also indicate 
  247.                      * the exact amount of data in the 
  248.                      * request buffers.  The reply fields 
  249.                      * are initialized to NIL for the
  250.                       * pointers and 0 for the lengths.  
  251.                      * This can be passed to Rpc_Reply */
  252. {
  253.     Fs_HandleHeader    *hdrPtr;    /* I/O handle created by type-specific
  254.                      * open routine. */
  255.     ReturnStatus    status;
  256.     FsDeviceRemoteOpenParam *paramPtr;
  257.     register int    dataSize;
  258.     ClientData        streamData;
  259.  
  260.     /*
  261.      * Call the client-open routine to set up an I/O handle here on the
  262.      * I/O server for the device.  This is either the device, pipe, or
  263.      * named pipe open routine.  We allocate storage and copy the stream
  264.      * data so the CltOpen routine can free it, as it expects to do.
  265.      * NAME note: we don't have a name for the device here.
  266.      */
  267.     paramPtr = (FsDeviceRemoteOpenParam *) storagePtr->requestParamPtr;
  268.     dataSize = paramPtr->dataSize;
  269.     if (dataSize > 0) {
  270.     streamData = (ClientData)malloc(dataSize);
  271.     bcopy((Address)¶mPtr->openData, (Address)streamData, dataSize);
  272.     } else {
  273.     streamData = (ClientData)NIL;
  274.     }
  275.     paramPtr->fileID.type = Fsio_MapRmtToLclType(paramPtr->fileID.type);
  276.     if (paramPtr->fileID.type < 0) {
  277.     return(GEN_INVALID_ARG);
  278.     }
  279.     status = (fsio_StreamOpTable[paramPtr->fileID.type].ioOpen)
  280.             (¶mPtr->fileID, ¶mPtr->useFlags,
  281.              clientID, streamData, (char *)NIL, &hdrPtr);
  282.     if (status == SUCCESS) {
  283.     /*
  284.      * Return the fileID to the other host so it can
  285.      * set up its own I/O handle.
  286.      */
  287.     storagePtr->replyParamPtr = (Address)&hdrPtr->fileID;
  288.     storagePtr->replyParamSize = sizeof(Fs_FileID);
  289.     }
  290.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  291.     return(SUCCESS);    /* So that Rpc_Server doesn't send error reply */
  292. }
  293.  
  294. /*
  295.  *----------------------------------------------------------------------
  296.  *
  297.  * Fsrmt_IOClose --
  298.  *
  299.  *    Close a stream to a remote device/pipe.  We just need to clean up our
  300.  *    connection to the I/O server.  (The file server that named the
  301.  *    device file keeps no state about us, so we don't have to contact it.)
  302.  *    We make an RPC to the I/O server which invokes close routine there.
  303.  *    We also update our own use counts.
  304.  *
  305.  * Results:
  306.  *    SUCCESS.
  307.  *
  308.  * Side effects:
  309.  *    RPC to the I/O server to invoke Fsio_DeviceClose/Fsio_PipeClose.
  310.  *    Release the remote I/O handle.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314. #ifdef SOSP91
  315. ReturnStatus
  316. Fsrmt_IOClose(streamPtr, clientID, procID, flags, dataSize, closeData,
  317.     offsetPtr, rwFlagsPtr)
  318. #else
  319. ReturnStatus
  320. Fsrmt_IOClose(streamPtr, clientID, procID, flags, dataSize, closeData)
  321. #endif
  322.     Fs_Stream        *streamPtr;    /* Stream to remote object */
  323.     int            clientID;    /* ID of closing host */
  324.     Proc_PID        procID;        /* ID of closing process */
  325.     int            flags;        /* Flags from the stream being closed */
  326.     int            dataSize;    /* Size of *closeData, or Zero */
  327.     ClientData        closeData;    /* Copy of cached I/O attributes. */
  328. #ifdef SOSP91
  329.     int            *offsetPtr;    /* Not used. */
  330.     int            *rwFlagsPtr;    /* Not used. */
  331. #endif
  332. {
  333.     ReturnStatus        status;
  334.     register Fsrmt_IOHandle *rmtHandlePtr =
  335.         (Fsrmt_IOHandle *)streamPtr->ioHandlePtr;
  336.  
  337.     /*
  338.      * Decrement local references.
  339.      */
  340.     rmtHandlePtr->recovery.use.ref--;
  341.     if (flags & FS_WRITE) {
  342.     rmtHandlePtr->recovery.use.write--;
  343.     }
  344.  
  345.     if (rmtHandlePtr->recovery.use.ref < 0 ||
  346.     rmtHandlePtr->recovery.use.write < 0) {
  347.     panic( "Fsrmt_IOClose: <%d,%d> ref %d write %d\n",
  348.         rmtHandlePtr->hdr.fileID.major, rmtHandlePtr->hdr.fileID.minor,
  349.         rmtHandlePtr->recovery.use.ref,
  350.         rmtHandlePtr->recovery.use.write);
  351.     }
  352.  
  353.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  354.     status = FS_STALE_HANDLE;
  355.     } else {
  356.     status = Fsrmt_Close(streamPtr, clientID, procID, flags,
  357.                    dataSize, closeData);
  358.     }
  359.     /*
  360.      * Check the number of users with the handle still locked, then
  361.      * remove the handle if we aren't using it anymore.  Note that if
  362.      * we get an RPC timeout we hold onto the handle and will do a
  363.      * reopen later to reconcile the server with our state.  A transient
  364.      * communication failure, for example, would otherwise cause a close
  365.      * to be dropped and leave lingering references to the device
  366.      * on the I/O server.
  367.      */
  368.     if (status == SUCCESS && rmtHandlePtr->recovery.use.ref == 0) {
  369.     /*
  370.      * Undo the callback we registered when we created the remote handle.
  371.      * Then nuke the handle itself.
  372.      */
  373.     Recov_RebootUnRegister(rmtHandlePtr->hdr.fileID.serverID, Fsutil_Reopen,
  374.                 (ClientData)NIL);
  375.     Fsutil_RecoverySyncLockCleanup(&rmtHandlePtr->recovery);
  376.     Fsutil_HandleRelease(rmtHandlePtr, TRUE);
  377.     Fsutil_HandleRemove(rmtHandlePtr);
  378.     fs_Stats.object.remote--;
  379.     } else {
  380.     Fsutil_HandleRelease(rmtHandlePtr, TRUE);
  381.     }
  382.     return(status);
  383. }
  384.  
  385. /*
  386.  * Parameters for a device reopen RPC used to reestablish state on
  387.  * the I/O server for a device.
  388.  */
  389. typedef struct FsRmtDeviceReopenParams {
  390.     Fs_FileID    fileID;        /* File ID of file to reopen. MUST BE FIRST! */
  391.     Fsio_UseCounts use;        /* Device usage information */
  392. } FsRmtDeviceReopenParams;
  393.  
  394. /*
  395.  *----------------------------------------------------------------------
  396.  *
  397.  * FsrmtDeviceReopen --
  398.  *
  399.  *    Reopen a remote device at the I/O server.  This sets up and conducts an 
  400.  *    RPC_FS_DEV_REOPEN remote procedure call to re-open the remote device.
  401.  *
  402.  * Results:
  403.  *    None.
  404.  *
  405.  * Side effects:
  406.  *    None.
  407.  *    
  408.  *
  409.  *----------------------------------------------------------------------
  410.  */
  411. /*ARGSUSED*/
  412. ReturnStatus
  413. FsrmtDeviceReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  414.     Fs_HandleHeader    *hdrPtr;    /* Device I/O handle to reopen */
  415.     int            clientID;    /* Client doing the reopen */
  416.     ClientData        inData;        /* IGNORED */
  417.     int            *outSizePtr;    /* Size of returned data, 0 here */
  418.     ClientData        *outDataPtr;    /* Returned data, NIL here */
  419. {
  420.     register Fsrmt_IOHandle    *handlePtr = (Fsrmt_IOHandle *)hdrPtr;
  421.     ReturnStatus        status;
  422.     int                outSize;
  423.     FsRmtDeviceReopenParams    reopenParams;
  424.  
  425.     /*
  426.      * Set up reopen parameters.  fileID must be first in order
  427.      * to use the generic FsrmtReopen/Fsrmt_RpcReopen stubs.
  428.      */
  429.     reopenParams.fileID = handlePtr->hdr.fileID;
  430.     reopenParams.use = handlePtr->recovery.use;
  431.  
  432.     outSize = 0;
  433.     status = FsrmtReopen(hdrPtr, sizeof(reopenParams),
  434.                 (Address)&reopenParams, &outSize, (Address)NIL);
  435.     return(status);
  436. }
  437.  
  438.  
  439. /*
  440.  * ----------------------------------------------------------------------------
  441.  *
  442.  * Fsrmt_IOMigClose --
  443.  *
  444.  *    Release a reference on a remote I/O handle.  This decrements
  445.  *    recovery use counts as well as releasing the handle.
  446.  *    
  447.  * Results:
  448.  *    SUCCESS.
  449.  *
  450.  * Side effects:
  451.  *    Decrement recovery use counts and release the I/O handle.
  452.  *
  453.  * ----------------------------------------------------------------------------
  454.  *
  455.  */
  456. /*ARGSUSED*/
  457. ReturnStatus
  458. Fsrmt_IOMigClose(hdrPtr, flags)
  459.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  460.     int flags;            /* Use flags from the stream */
  461. {
  462.     register Fsrmt_IOHandle *rmtHandlePtr = (Fsrmt_IOHandle *)hdrPtr;
  463.  
  464.     Fsutil_HandleLock(rmtHandlePtr);
  465.     rmtHandlePtr->recovery.use.ref--;
  466.     if (flags & FS_WRITE) {
  467.     rmtHandlePtr->recovery.use.write--;
  468.     }
  469.     if (flags & FS_EXECUTE) {
  470.     rmtHandlePtr->recovery.use.exec--;
  471.     }
  472.     Fsutil_HandleRelease(rmtHandlePtr, TRUE);
  473.     return(SUCCESS);
  474. }
  475.  
  476. /*
  477.  * ----------------------------------------------------------------------------
  478.  *
  479.  * FsrmtDeviceMigrate --
  480.  *
  481.  *    This takes care of transfering references from one client to the other.
  482.  *    A useful side-effect of this routine is    to properly set the type in
  483.  *    the ioFileID, either FSIO_LCL_DEVICE_STREAM or FSIO_RMT_DEVICE_STREAM.
  484.  *    In the latter case FsDevoceMigrate is called to do all the work.
  485.  *
  486.  * Results:
  487.  *    An error status if the I/O handle can't be set-up.
  488.  *    Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
  489.  *    bit set, and *sizePtr and *dataPtr are set to reference Fsio_DeviceState.
  490.  *
  491.  * Side effects:
  492.  *    Sets the correct stream type on the ioFileID.
  493.  *    Shifts client references from the srcClient to the destClient.
  494.  *    Set up and return Fsio_DeviceState for use by the MigEnd routine.
  495.  *
  496.  * ----------------------------------------------------------------------------
  497.  *
  498.  */
  499. /*ARGSUSED*/
  500. ReturnStatus
  501. FsrmtDeviceMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  502.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  503.     int        dstClientID;    /* ID of target client */
  504.     int        *flagsPtr;    /* In/Out Stream usage flags */
  505.     int        *offsetPtr;    /* Return - the new stream offset */
  506.     int        *sizePtr;    /* Return - sizeof(Fsio_DeviceState) */
  507.     Address    *dataPtr;    /* Return - pointer to Fsio_DeviceState */
  508. {
  509.     register ReturnStatus        status;
  510.  
  511.     if (migInfoPtr->ioFileID.serverID == rpc_SpriteID) {
  512.     /*
  513.      * The device was remote, which is why we were called, but is now local.
  514.      */
  515.     migInfoPtr->ioFileID.type = FSIO_LCL_DEVICE_STREAM;
  516.     return(Fsio_DeviceMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  517.         sizePtr, dataPtr));
  518.     }
  519.     migInfoPtr->ioFileID.type = FSIO_RMT_DEVICE_STREAM;
  520.     status = Fsrmt_NotifyOfMigration(migInfoPtr, flagsPtr, offsetPtr,
  521.                 0, (Address)NIL);
  522.     if (status != SUCCESS) {
  523.     printf( "FsrmtDeviceMigrate, server error <%x>\n",
  524.         status);
  525.     } else {
  526.     *dataPtr = (Address)NIL;
  527.     *sizePtr = 0;
  528.     }
  529.     return(status);
  530. }
  531.  
  532. /*
  533.  * ----------------------------------------------------------------------------
  534.  *
  535.  * Fsrmt_IOMigOpen --
  536.  *
  537.  *    Create a FSIO_RMT_DEVICE_STREAM or FSIO_RMT_PIPE_STREAM after migration.
  538.  *    The srvMigrate routine has done most all the work.
  539.  *    We just grab a reference on the I/O handle for the stream.
  540.  *
  541.  * Results:
  542.  *    Sets the I/O handle.
  543.  *
  544.  * Side effects:
  545.  *    May install the handle.  Ups use and reference counts.
  546.  *
  547.  * ----------------------------------------------------------------------------
  548.  *
  549.  */
  550. /*ARGSUSED*/
  551. ReturnStatus
  552. Fsrmt_IOMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  553.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  554.     int        size;        /* Zero */
  555.     ClientData    data;        /* NIL */
  556.     Fs_HandleHeader **hdrPtrPtr;    /* Return - handle for the file */
  557. {
  558.     register Fsrmt_IOHandle *rmtHandlePtr;
  559.     register Fsutil_RecoveryInfo *recovPtr;
  560.     Boolean found;
  561.  
  562.     found = Fsutil_HandleInstall(&migInfoPtr->ioFileID, sizeof(Fsrmt_IOHandle),
  563.         (char *)NIL, FALSE, hdrPtrPtr);
  564.     rmtHandlePtr = (Fsrmt_IOHandle *)*hdrPtrPtr;
  565.     recovPtr = &rmtHandlePtr->recovery;
  566.     if (!found) {
  567.     Fsutil_RecoveryInit(recovPtr);
  568.     fs_Stats.object.remote++;
  569.     /*
  570.      * Register a callback with the recovery module.  This ensures that
  571.      * someone is paying attention to the I/O server and the filesystem
  572.      * will get called back when the I/O server reboots.
  573.      */
  574.     Recov_RebootRegister(migInfoPtr->ioFileID.serverID, Fsutil_Reopen,
  575.                 (ClientData)NIL);
  576.     }
  577.     recovPtr->use.ref++;
  578.     if (migInfoPtr->flags & FS_WRITE) {
  579.     recovPtr->use.write++;
  580.     }
  581.     Fsutil_HandleUnlock(rmtHandlePtr);
  582.     return(SUCCESS);
  583. }
  584.  
  585. /*
  586.  *----------------------------------------------------------------------
  587.  *
  588.  * FsrmtDeviceVerify --
  589.  *
  590.  *    Verify that the remote client is known for the device, and return
  591.  *    a locked pointer to the device's I/O handle.
  592.  *
  593.  * Results:
  594.  *    A pointer to the I/O handle for the device, or NIL if
  595.  *    the client is bad.
  596.  *
  597.  * Side effects:
  598.  *    The handle is returned locked and with its refCount incremented.
  599.  *    It should be released with Fsutil_HandleRelease.
  600.  *
  601.  *----------------------------------------------------------------------
  602.  */
  603.  
  604. Fs_HandleHeader *
  605. FsrmtDeviceVerify(fileIDPtr, clientID, domainTypePtr)
  606.     Fs_FileID    *fileIDPtr;    /* Client's I/O file ID */
  607.     int        clientID;    /* Host ID of the client */
  608.     int        *domainTypePtr;    /* Return - FS_LOCAL_DOMAIN */
  609. {
  610.     register Fsio_DeviceIOHandle    *devHandlePtr;
  611.     register Fsconsist_ClientInfo    *clientPtr;
  612.     Boolean            found = FALSE;
  613.  
  614.     fileIDPtr->type = Fsio_MapRmtToLclType(fileIDPtr->type);
  615.     if (fileIDPtr->type != FSIO_LCL_DEVICE_STREAM) {
  616.     printf("FsrmtDeviceVerify, bad file ID type\n");
  617.     return((Fs_HandleHeader *)NIL);
  618.     }
  619.     devHandlePtr = Fsutil_HandleFetchType(Fsio_DeviceIOHandle, fileIDPtr);
  620.     if (devHandlePtr != (Fsio_DeviceIOHandle *)NIL) {
  621.     LIST_FORALL(&devHandlePtr->clientList, (List_Links *) clientPtr) {
  622.         if (clientPtr->clientID == clientID) {
  623.         found = TRUE;
  624.         break;
  625.         }
  626.     }
  627.     if (!found) {
  628.         Fsutil_HandleRelease(devHandlePtr, TRUE);
  629.         devHandlePtr = (Fsio_DeviceIOHandle *)NIL;
  630.     }
  631.     }
  632.     if (!found) {
  633.     printf("FsrmtDeviceVerify, client %d not known for device <%d,%d>\n",
  634.         clientID, fileIDPtr->major, fileIDPtr->minor);
  635.     }
  636.     if (domainTypePtr != (int *)NIL) {
  637.     *domainTypePtr = FS_LOCAL_DOMAIN;
  638.     }
  639.     return((Fs_HandleHeader *)devHandlePtr);
  640. }
  641.  
  642. /*
  643.  *----------------------------------------------------------------------
  644.  *
  645.  * Fsrmt_DeviceReopen --
  646.  *
  647.  *    Reopen a device here on the I/O server.
  648.  *
  649.  * Results:
  650.  *    None.
  651.  *
  652.  * Side effects:
  653.  *    None.
  654.  *    
  655.  *
  656.  *----------------------------------------------------------------------
  657.  */
  658. /*ARGSUSED*/
  659. ReturnStatus
  660. Fsrmt_DeviceReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  661.     Fs_HandleHeader    *hdrPtr;    /* NIL on the I/O server */
  662.     int            clientID;    /* Client doing the reopen */
  663.     ClientData        inData;        /* Ref. to FsRmtDeviceReopenParams */
  664.     int            *outSizePtr;    /* Size of returned data, 0 here */
  665.     ClientData        *outDataPtr;    /* Returned data, NIL here */
  666. {
  667.     Fsio_DeviceIOHandle    *devHandlePtr;
  668.     ReturnStatus    status;
  669.     register        devIndex;
  670.     register FsRmtDeviceReopenParams *paramPtr =
  671.         (FsRmtDeviceReopenParams *)inData;
  672.  
  673.     *outDataPtr = (ClientData) NIL;
  674.     *outSizePtr = 0;
  675.  
  676.     (void) FsioDeviceHandleInit(¶mPtr->fileID, (char *)NIL, &devHandlePtr); 
  677.  
  678.     devIndex = DEV_TYPE_INDEX(devHandlePtr->device.type);
  679.     if (devIndex >= devNumDevices) {
  680.     status = FS_DEVICE_OP_INVALID;
  681.     } else {
  682.     /*
  683.      * Compute the difference between the client's and our version
  684.      * of the client's use state, and then call the device driver
  685.      * with that information.  We may have missed opens (across a
  686.      * reboot) or closes (during transient communication failures)
  687.      * so the net difference may be positive or negative.
  688.      */
  689.     Fsconsist_IOClientStatus(&devHandlePtr->clientList, clientID, ¶mPtr->use);
  690.     if (paramPtr->use.ref == 0) {
  691.         status = SUCCESS;    /* No change visible to driver */
  692.     } else if (paramPtr->use.ref > 0) {
  693.         /*
  694.          * Reestablish open connections.
  695.          */
  696.         status = (*devFsOpTable[devIndex].reopen)(&devHandlePtr->device,
  697.                     paramPtr->use.ref, paramPtr->use.write,
  698.                     (Fs_NotifyToken)devHandlePtr,
  699.                     &devHandlePtr->flags);
  700.         if (status == SUCCESS) {
  701.         (void)Fsconsist_IOClientReopen(&devHandlePtr->clientList, clientID,
  702.                      ¶mPtr->use);
  703.         devHandlePtr->use.ref += paramPtr->use.ref;
  704.         devHandlePtr->use.write += paramPtr->use.write;
  705.         }
  706.     } else {
  707.         /*
  708.          * Clean up closed connections.  Note, we assume that
  709.          * the client was reading, even though it may have had
  710.          * a write-only stream.  This could break syslog, which
  711.          * is a single-reader/multiple-writer stream.  "ref" should
  712.          * be changed to "read".
  713.          */
  714.         int useFlags = FS_READ;
  715.         if (paramPtr->use.write > 0) {
  716.         useFlags |= FS_WRITE;
  717.         }
  718.         status = FsioDeviceCloseInt(devHandlePtr, useFlags, paramPtr->use.ref,
  719.                             paramPtr->use.write);
  720.      }
  721.     }
  722.     Fsutil_HandleRelease(devHandlePtr, TRUE);
  723.     return(status);
  724. }
  725.  
  726.